package com.itjeffrey.autocode.common;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itjeffrey.autocode.constant.SysConstant;
import com.itjeffrey.autocode.enums.ExceptionEnum;
import com.itjeffrey.autocode.exception.ACException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import java.util.List;

/**
 * 通用异常处理器
 *
 * @From: Jeffrey
 * @Date: 2020/11/8
 */
@Slf4j
@RestControllerAdvice
public class CommonExceptionHandler {

    /**
     * 自定义异常处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(ACException.class)
    public ResponseEntity<Result> handleException(ACException exception) {
        if (exception.getErrMsg() != null) {
            log.error("异常代码：{} -> 异常信息：{}", exception.getErrCode(), exception.getErrMsg());
            return ResponseEntity.ok(new Result(exception));
        }
        log.error("异常代码：{} -> 异常信息：{}", exception.getExceptionEnum().getErrorCode(), exception.getExceptionEnum()
                .getErrorMessage());
        exception.printStackTrace();
        ExceptionEnum exceptionEnum = exception.getExceptionEnum();
        return ResponseEntity.ok(new Result(exceptionEnum));
    }

    /**
     * 无权访问异常处理
     * @param exception
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<Result> handleException(AccessDeniedException exception){
        return ResponseEntity.status(HttpStatus.FORBIDDEN.value()).body(Result.fail(ExceptionEnum.NO_AUTH_TO_VISIT));
    }

    /**
     * 方法参数校验异常处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Result> handleException(MethodArgumentNotValidException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        JSONArray ja = new JSONArray();
        for (FieldError fieldError : fieldErrors) {
            JSONObject jo = new JSONObject();
            jo.put("Field", fieldError.getField());
            jo.put("Message", fieldError.getDefaultMessage());
            ja.add(jo);
        }
        log.error("参数校验错误 -> {}", ja.toJSONString());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR.value()).body(
                Result.fail(ExceptionEnum.ARGUMENT_VALIDATE_ERROR.getErrorCode(),
                        ExceptionEnum.ARGUMENT_VALIDATE_ERROR.getErrorMessage(), ja)
        );
    }

    /**
     * 文件上传异常处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<Result> handleException(MaxUploadSizeExceededException exception) {
        log.error("最大上传大小：{} -> 异常信息：{}", exception.getMaxUploadSize(), exception.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Result(ExceptionEnum
                .FILE_SIZE_EXCEEDD, SysConstant.DEFAULT_MAX_FILE_SIZE));
    }

    /**
     * 通用异常处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Result> handleException(Exception exception) {
        exception.printStackTrace();
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Result(ExceptionEnum.UNKNOWN_ERROR));
    }

}
